using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using UwinEducation.Application.Common.Interfaces;
using UwinEducation.Application.Common.Interfaces.Orders;
using UwinEducation.Application.Dtos;
using UwinEducation.Application.Dtos.Orders;
using UwinEducation.Application.Extensions;
using UwinEducation.Application.Services.Orders;
using UwinEducation.Domain.Entities;
using UwinEducation.Domain.IRepositories;
using UwinEducation.Infrastructure.Persistence;
using UwinEducation.Shared.Enums;
using UwinEducation.Shared.Exceptions;
using UwinEducation.Shared.Models;
using UwinEducation.Shared.Services;

namespace UwinEducation.Application.Services
{
    /// <summary>
    /// 教师课表服务实现
    /// </summary>
    public class TeacherScheduleService : ITeacherScheduleService
    {
        private readonly ITeacherScheduleRepository _teacherScheduleRepository;
        private readonly ITeacherScheduleDetailsRepository _teacherScheduleDetailsRepository;
        private readonly ITeacherRepository _teacherRepository;
        private readonly ICourseRepository _courseRepository;
        private readonly IClassroomRepository _classroomRepository;
        private readonly IStudentScheduleService _studentScheduleService;
        private readonly IAppointmentService _appointmentService;
        private readonly IOrderDetailService _orderDetailService;
        private readonly ICurrentUserService _currentUserService;

        private readonly IStudentScheduleDetailsRepository _studentScheduleDetailsRepository;

        private readonly ApplicationDbContext _context;
        private readonly IMapper _mapper;
        private readonly IStudentScheduleRepository _studentScheduleRepository;
        private readonly IServiceProvider _serviceProvider;

        public TeacherScheduleService(
            ITeacherScheduleRepository teacherScheduleRepository,
            ITeacherScheduleDetailsRepository teacherScheduleDetailsRepository,
            ITeacherRepository teacherRepository,
            ICourseRepository courseRepository,
            IClassroomRepository classroomRepository,
            IStudentScheduleService studentScheduleService,
            IAppointmentService appointmentService,
            IOrderDetailService orderDetailService,
            ICurrentUserService currentUserService,
            IMapper mapper,
            ApplicationDbContext context,
            IStudentScheduleRepository studentScheduleRepository,
            IStudentScheduleDetailsRepository studentScheduleDetailsRepository,
            IServiceProvider serviceProvider
        )
        {
            _teacherScheduleRepository = teacherScheduleRepository;
            _teacherScheduleDetailsRepository = teacherScheduleDetailsRepository;
            _teacherRepository = teacherRepository;
            _courseRepository = courseRepository;
            _classroomRepository = classroomRepository;
            _studentScheduleService = studentScheduleService;
            _appointmentService = appointmentService;
            _orderDetailService = orderDetailService;
            _currentUserService = currentUserService;
            _mapper = mapper;
            _context = context;
            _studentScheduleRepository = studentScheduleRepository;
            _serviceProvider = serviceProvider;
            _studentScheduleDetailsRepository = studentScheduleDetailsRepository;
        }

        /// <summary>
        /// 获取教师课表分页列表
        /// </summary>
        public async Task<PagedResult<TeacherScheduleDto>> GetPagedListAsync(
            TeacherSchedulePageRequest pageRequest
        )
        {
            return await GetPagedStatisticalDetailsListAsync(pageRequest);

            //// 1. 获取课表基本信息
            //var result = await _teacherScheduleDetailsRepository.GetPagedDetailsListAsync(
            //    pageRequest
            //);

            //// 2. 获取所有课表明细ID
            //var teacherScheduleDetailsIds = result.Items.Select(ts => ts.Id).ToList();

            //// 3. 获取每个课表的报名人数
            //var enrolledCounts =
            //    await _studentScheduleRepository.GetEnrolledCountByTeacherScheduleDetailsIdsAsync(
            //        teacherScheduleDetailsIds
            //    );

            //// 4. 映射并设置报名人数

            //var ts = result
            //    .Items.Select(x => new TeacherSchedule()
            //    {
            //        Id = x.Id,
            //        TeacherId = x.TeacherSchedule.TeacherId,
            //        CourseId = x.TeacherSchedule.CourseId,
            //        ClassroomId = x.TeacherSchedule.ClassroomId,
            //        UnitPrice = x.TeacherSchedule.UnitPrice,
            //        Capacity = x.TeacherSchedule.Capacity,
            //        StartTime = x.StartTime,
            //        EndTime = x.EndTime,
            //        GroupId = x.TeacherSchedule.Id,
            //        IsForceCheck = x.TeacherSchedule.IsForceCheck,
            //        Status = x.Status,
            //        Reason = x.Reason,
            //        Remarks = x.Remarks,
            //        Classroom = x.TeacherSchedule.Classroom,
            //        Course = x.TeacherSchedule.Course,
            //        Teacher = x.TeacherSchedule.Teacher,
            //    })
            //    .ToList();

            //var dtos = _mapper.Map<List<TeacherScheduleDto>>(ts);

            //// 5. 设置报名人数
            //foreach (var dto in dtos)
            //{
            //    var enrolledCount = enrolledCounts.FirstOrDefault(x =>
            //        x.TeacherScheduleDetailsId == dto.Id
            //    );
            //    dto.EnrolledCount = enrolledCount.EnrolledCount;
            //}

            //return new PagedResult<TeacherScheduleDto> { Total = result.Total, Items = dtos };
        }

        public async Task<PagedResult<TeacherScheduleDto>> GetCalendarListAsync(
            TeacherSchedulePageRequest pageRequest
        )
        {
            var studentScheduleDetailsGroups = _context
                .StudentScheduleDetails.AsNoTracking()
                .Where(o => o.OrderDetail != null && !o.OrderDetail.Student.IsDeleted)
                .GroupBy(o => o.TeacherScheduleDetailsId)
                .Select(g => new { TeacherScheduleDetailsId = g.Key, EnrolledCount = g.Count() });

            var query = _context.TeacherScheduleDetails.AsQueryable();

            //根据pageRequest进行分页，条件过滤
            if (pageRequest.TeacherId.HasValue)
            {
                query = query.Where(x => x.TeacherSchedule.TeacherId == pageRequest.TeacherId);
            }
            if (pageRequest.GroupId.HasValue)
            {
                query = query.Where(x => x.TeacherScheduleId == pageRequest.GroupId);
            }
            //时间范围
            if (pageRequest.StartDate.HasValue && pageRequest.EndDate.HasValue)
            {
                query = query.Where(x =>
                    x.StartTime >= pageRequest.StartDate && x.EndTime <= pageRequest.EndDate
                );
            }

            //应用Include和分页
            var teacherScheduleDetails = await query
                .Include(ts => ts.TeacherSchedule)
                .Include(ts => ts.TeacherSchedule.Classroom)
                .Include(ts => ts.TeacherSchedule.Teacher)
                .Include(ts => ts.TeacherSchedule.Course)
                .Skip((pageRequest.PageIndex - 1) * pageRequest.PageSize)
                .Take(pageRequest.PageSize)
                .ToListAsync();

            var result = teacherScheduleDetails
                .GroupJoin(
                    studentScheduleDetailsGroups,
                    ts => ts.Id,
                    s => s.TeacherScheduleDetailsId,
                    (ts, s) => new { ts, s }
                )
                .SelectMany(x => x.s.DefaultIfEmpty(), (ts, s) => new { ts = ts.ts, s });

            var dtos = result
                .Select(x => new TeacherScheduleDto()
                {
                    Id = x.ts.Id,
                    TeacherId = x.ts.TeacherSchedule.TeacherId,
                    CourseId = x.ts.TeacherSchedule.CourseId,
                    ClassroomId = x.ts.TeacherSchedule.ClassroomId,
                    UnitPrice = x.ts.TeacherSchedule.UnitPrice,
                    Capacity = x.ts.TeacherSchedule.Capacity,
                    StartTime = x.ts.StartTime,
                    EndTime = x.ts.EndTime,
                    GroupId = x.ts.TeacherSchedule.Id,
                    Status = x.ts.Status,
                    Reason = x.ts.Reason,
                    Remarks = x.ts.Remarks,
                    CalenderColor = x.ts.TeacherSchedule.Course?.CalendarColor ?? string.Empty,
                    ClassroomName = x.ts.TeacherSchedule.Classroom?.Name ?? string.Empty,
                    CourseName = x.ts.TeacherSchedule.Course?.Name ?? string.Empty,
                    TeacherName = x.ts.TeacherSchedule.Teacher?.Name ?? string.Empty,
                    EnrolledCount = x.s?.EnrolledCount ?? 0,
                    CourseType = x.ts.CourseType,
                })
                .ToList();

            var pagedResult = new PagedResult<TeacherScheduleDto>()
            {
                Total = dtos.Count,
                Items = dtos,
            };
            return pagedResult;
        }

        public async Task<PagedResult<TeacherScheduleDto>> GetPagedStatisticalDetailsListAsync(
            TeacherSchedulePageRequest pageRequest
        )
        {
            var studentScheduleDetailsGroups = _context
                .StudentScheduleDetails.AsNoTracking()
                .Where(o =>
                    o.Status == ScheduleStatus.Normal
                    && o.OrderDetail != null
                    && !o.OrderDetail.Student.IsDeleted
                )
                .GroupBy(o => o.TeacherScheduleDetailsId)
                .Select(g => new { TeacherScheduleDetailsId = g.Key, EnrolledCount = g.Count() });

            var query = _context.TeacherScheduleDetails.AsQueryable();

            //根据pageRequest进行分页，条件过滤
            if (pageRequest.TeacherId.HasValue)
            {
                query = query.Where(x => x.TeacherSchedule.TeacherId == pageRequest.TeacherId);
            }
            if (pageRequest.GroupId.HasValue)
            {
                query = query.Where(x => x.TeacherScheduleId == pageRequest.GroupId);
            }
            //时间范围
            if (pageRequest.StartDate.HasValue && pageRequest.EndDate.HasValue)
            {
                query = query.Where(x =>
                    x.StartTime >= pageRequest.StartDate && x.EndTime <= pageRequest.EndDate
                );
            }

            //应用Include和分页
            var teacherScheduleDetails = await query
                .Include(ts => ts.TeacherSchedule)
                .Include(ts => ts.TeacherSchedule.Classroom)
                .Include(ts => ts.TeacherSchedule.Teacher)
                .Include(ts => ts.TeacherSchedule.Course)
                .Skip((pageRequest.PageIndex - 1) * pageRequest.PageSize)
                .Take(pageRequest.PageSize)
                .ToListAsync();

            var result = teacherScheduleDetails
                .GroupJoin(
                    studentScheduleDetailsGroups,
                    ts => ts.Id,
                    s => s.TeacherScheduleDetailsId,
                    (ts, s) => new { ts, s }
                )
                .SelectMany(x => x.s.DefaultIfEmpty(), (ts, s) => new { ts = ts.ts, s });

            //var query = _context
            //    .TeacherScheduleDetails.Include(tsd => tsd.TeacherSchedule)
            //    .Include(tsd => tsd.TeacherSchedule.Classroom)
            //    .Include(tsd => tsd.TeacherSchedule.Teacher)
            //    .Include(tsd => tsd.TeacherSchedule.Course)
            //    .GroupJoin(
            //        studentScheduleDetailsGroups,
            //        ts => ts.Id,
            //        s => s.TeacherScheduleDetailsId,
            //        (ts, s) => new { ts, s }
            //    ).SelectMany(x => x.s.DefaultIfEmpty(), (ts, s) => new { ts = ts.ts, s });

            ////根据pageRequest进行分页，条件过滤
            //if (pageRequest.TeacherId.HasValue)
            //{
            //    query = query.Where(x => x.ts.TeacherSchedule.TeacherId == pageRequest.TeacherId);
            //}
            ////时间范围
            //if (pageRequest.StartDate.HasValue && pageRequest.EndDate.HasValue)
            //{
            //    query = query.Where(x =>
            //        x.ts.StartTime >= pageRequest.StartDate && x.ts.EndTime <= pageRequest.EndDate
            //    );
            //}

            //var result = query
            //    .Skip((pageRequest.PageIndex - 1) * pageRequest.PageSize)
            //    .Take(pageRequest.PageSize)
            //    .ToList();

            var dtos = result
                .Select(x => new TeacherScheduleDto()
                {
                    Id = x.ts.Id,
                    TeacherId = x.ts.TeacherSchedule.TeacherId,
                    CourseId = x.ts.TeacherSchedule.CourseId,
                    ClassroomId = x.ts.TeacherSchedule.ClassroomId,
                    UnitPrice = x.ts.TeacherSchedule.UnitPrice,
                    Capacity = x.ts.TeacherSchedule.Capacity,
                    StartTime = x.ts.StartTime,
                    EndTime = x.ts.EndTime,
                    GroupId = x.ts.TeacherSchedule.Id,
                    Status = x.ts.Status,
                    Reason = x.ts.Reason,
                    Remarks = x.ts.Remarks,
                    CalenderColor = x.ts.TeacherSchedule.Course?.CalendarColor ?? string.Empty,
                    ClassroomName = x.ts.TeacherSchedule.Classroom?.Name ?? string.Empty,
                    CourseName = x.ts.TeacherSchedule.Course?.Name ?? string.Empty,
                    TeacherName = x.ts.TeacherSchedule.Teacher?.Name ?? string.Empty,
                    EnrolledCount = x.s?.EnrolledCount ?? 0,
                    CourseType = x.ts.CourseType,
                })
                .ToList();

            var pagedResult = new PagedResult<TeacherScheduleDto>()
            {
                Total = dtos.Count,
                Items = dtos,
            };
            return pagedResult;

            // var result = await _teacherScheduleDetailsRepository.GetPagedStatisticalDetailsListAsync(pageRequest);
            // return _mapper.Map<PagedResult<TeacherScheduleDto>>(result);
        }

        public async Task<TeacherScheduleDto> GetByIdAsync(Guid id)
        {
            var scheduleDetails = await _teacherScheduleDetailsRepository.GetByIdAsync(id);
            if (scheduleDetails == null)
            {
                throw new ArgumentException($"课表不存在: {id}");
            }
            var schedule = new TeacherSchedule()
            {
                Id = scheduleDetails.Id,
                TeacherId = scheduleDetails.TeacherSchedule.TeacherId,
                CourseId = scheduleDetails.TeacherSchedule.CourseId,
                ClassroomId = scheduleDetails.TeacherSchedule.ClassroomId,
                UnitPrice = scheduleDetails.TeacherSchedule.UnitPrice,
                Capacity = scheduleDetails.TeacherSchedule.Capacity,
                StartTime = scheduleDetails.StartTime,
                EndTime = scheduleDetails.EndTime,
                GroupId = scheduleDetails.TeacherSchedule.Id,
                IsForceCheck = scheduleDetails.TeacherSchedule.IsForceCheck,
                Status = scheduleDetails.Status,
                Reason = scheduleDetails.Reason,
                Remarks = scheduleDetails.Remarks,
                Classroom = scheduleDetails.TeacherSchedule.Classroom,
                Course = scheduleDetails.TeacherSchedule.Course,
                Teacher = scheduleDetails.TeacherSchedule.Teacher,
                CourseType = scheduleDetails.CourseType,
            };

            return _mapper.Map<TeacherScheduleDto>(schedule);
        }

        public async Task<List<TeacherScheduleDto>> CreateAsync(
            BatchCreateTeacherScheduleDto inputs
        )
        {
            List<string> businessExceptions = new List<string>();
            // 验证教师是否存在
            await ValidateTeacherExistenceAsync(inputs);

            // 验证课程是否存在
            await ValidateCourseExistenceAsync(inputs);

            // 验证时间是否合法
            ValidateScheduleTime(inputs);

            // 生成课表
            var teacherSchedules = inputs.GenerateSchedules();

            // 检查时间冲突
            await ValidateScheduleConflictsAsync(inputs, businessExceptions, teacherSchedules);

            // 验证教室是否存在
            await ValidateClassroomExistenceAsync(inputs, teacherSchedules, businessExceptions);

            if (inputs.IsForceCheck)
            {
                if (businessExceptions != null && businessExceptions.Count > 0)
                {
                    throw new BusinessException(businessExceptions, "TeacherSchedule");
                }
            }

            var schedule = TeacherSchedule.Create(
                inputs.TeacherId,
                inputs.CourseId,
                inputs.ClassroomId,
                inputs.UnitPrice,
                inputs.Capacity,
                inputs.StartTime,
                inputs.EndTime,
                new Guid(),
                inputs.IsForceCheck
            );
            schedule.TeacherScheduleDetails = teacherSchedules
                .Select(x =>
                    TeacherScheduleDetails.Create(
                        schedule.Id,
                        x.StartTime,
                        x.EndTime,
                        x.Status,
                        x.CourseType,
                        x.IsForceCheck,
                        x.Remarks
                    )
                )
                .ToList();

            //批量添加课表和学生课表添加到一个事务中
            using (var transaction = await _context.Database.BeginTransactionAsync())
            {
                try
                {
                    // 批量添加课表
                    await _teacherScheduleRepository.AddAsync(schedule);

                    // 批量添加学生课表
                    if (inputs.StudentIds != null && inputs.StudentIds.Count > 0)
                    {
                        // 废弃老师课表详情
                        if (inputs.AbandoningTeacherScheduleDetails != null)
                        {
                            await UpdateDetailsAsync(
                                new UpdateTeacherScheduleDetailsDto()
                                {
                                    Id = inputs
                                        .AbandoningTeacherScheduleDetails
                                        .TeacherScheduleDetailsId,
                                    Status = ScheduleStatus.Abandoned,
                                    Reason = inputs.AbandoningTeacherScheduleDetails.Reason,
                                }
                            );
                        }
                        // 批量添加学生课表

                        foreach (var item in inputs.StudentIds)
                        {
                            #region 旧代码
                            //using var scope = _serviceProvider.CreateScope();
                            //var studentScheduleService = scope.ServiceProvider.GetRequiredService<IStudentScheduleService>();

                            //await studentScheduleService.CreateRangeAsync(
                            //    new CreateStudentScheduleRangeDto
                            //    {
                            //        StudentId = item,
                            //        TeacherScheduleGroupId = schedule.Id,
                            //        IsForceCheck = inputs.IsStudentScheduleCheck,
                            //        StudentSchedules = schedule
                            //            .TeacherScheduleDetails.Select(
                            //                x => new CreateStudentScheduleRangeModel
                            //                {
                            //                    TeacherScheduleId = x.Id,
                            //                    Remarks = x.Remarks ?? string.Empty,
                            //                }
                            //            )
                            //            .ToList(),
                            //    }
                            //);
                            //using var scope = _serviceProvider.CreateScope();
                            //var orderDetailService =
                            //    scope.ServiceProvider.GetRequiredService<IOrderDetailService>();

                            #endregion

                            await _orderDetailService.AddAsync(
                                new CreateOrderDetailDto()
                                {
                                    OrderId = item.OrderId ?? Guid.Empty,
                                    StudentId = item.StudentId,
                                    TeacherScheduleId = schedule.Id,
                                    UnitPrice = schedule.UnitPrice,
                                    IsForceCheck = inputs.IsStudentScheduleCheck,
                                    StudentScheduleDetailsDtos = schedule
                                        .TeacherScheduleDetails.Select(
                                            x => new CreateStudentScheduleDetailsDtoBase
                                            {
                                                TeacherScheduleDetailsId = x.Id,
                                                CourseType = item.CourseType,
                                                Remarks = x.Remarks ?? string.Empty,
                                            }
                                        )
                                        .ToList(),
                                },
                                item.OrderId ?? Guid.Empty
                            );
                        }
                        //批量修改预约学生
                        if (inputs.AppointmentIds != null && inputs.AppointmentIds.Count > 0)
                        {
                            await _appointmentService.UpdateRangeAsync(inputs.AppointmentIds);
                        }
                    }

                    await transaction.CommitAsync();
                }
                catch (Exception ex)
                {
                    await transaction.RollbackAsync();
                    throw;
                }
            }
            return _mapper.Map<List<TeacherScheduleDto>>(teacherSchedules);
        }

        private async Task ValidateScheduleConflictsAsync(
            BatchCreateTeacherScheduleDto inputs,
            List<string> businessExceptions,
            List<TeacherSchedule> teacherSchedules
        )
        {
            //获取教师所有课表详情
            var teacherSchedulesDetails =
                await _teacherScheduleDetailsRepository.GetByTeacherIdAsync(
                    inputs.TeacherId,
                    inputs.StartTime,
                    inputs.EndTime.AddHours(23).AddMinutes(59).AddSeconds(59)
                );

            //检查时间冲突teacherSchedulesDetails和teacherSchedules
            foreach (var schedule in teacherSchedules)
            {
                // 时间段冲突的条件：
                // 1. 新开始时间在现有时间段内
                // 2. 新结束时间在现有时间段内
                // 3. 新时间段完全包含现有时间段
                var hasConflict = teacherSchedulesDetails
                    .Where(x => x.Status == ScheduleStatus.Normal)
                    .Any(x =>
                        (schedule.StartTime >= x.StartTime && schedule.StartTime < x.EndTime)
                        || (schedule.EndTime > x.StartTime && schedule.EndTime <= x.EndTime)
                        || (schedule.StartTime < x.StartTime && schedule.EndTime > x.EndTime)
                    );
                if (hasConflict)
                {
                    throw new ArgumentException(
                        $"时间冲突: {schedule.StartTime:yyyy-MM-dd HH:mm} - {schedule.EndTime:yyyy-MM-dd HH:mm}"
                    );
                    //businessExceptions.Add($"时间冲突: {schedule.StartTime:yyyy-MM-dd HH:mm} - {schedule.EndTime:yyyy-MM-dd HH:mm}");
                }
            }
        }

        private static void ValidateScheduleTime(BatchCreateTeacherScheduleDto inputs)
        {
            if (inputs.StartTime > inputs.EndTime)
            {
                throw new ArgumentException("开课日期必须早于结课日期");
            }
        }

        private async Task ValidateCourseExistenceAsync(BatchCreateTeacherScheduleDto inputs)
        {
            var course = await _courseRepository.GetByIdAsync(inputs.CourseId);
            if (course == null)
            {
                throw new ArgumentException($"课程不存在: {inputs.CourseId}");
            }
        }

        private async Task ValidateTeacherExistenceAsync(BatchCreateTeacherScheduleDto inputs)
        {
            var teacher = await _teacherRepository.GetByIdAsync(inputs.TeacherId);
            if (teacher == null)
            {
                throw new ArgumentException($"教师不存在: {inputs.TeacherId}");
            }
        }

        private async Task ValidateClassroomExistenceAsync(
            BatchCreateTeacherScheduleDto inputs,
            List<TeacherSchedule> teacherSchedules,
            List<string> businessExceptions
        )
        {
            if (inputs.ClassroomId.HasValue)
            {
                var classroom = await _classroomRepository.GetByIdAsync(inputs.ClassroomId.Value);
                if (classroom == null)
                {
                    throw new ArgumentException($"教室不存在: {inputs.ClassroomId}");
                }
                if (inputs.Capacity > classroom.Capacity)
                {
                    businessExceptions.Add(
                        $"教室容量不足: {inputs.ClassroomId},容量:{classroom.Capacity},需求:{inputs.Capacity}"
                    );
                    return;
                }

                // 校验时间范围内，教室容量是否足够，根据教室和时间范围内先查询老师课表
                var _teacherSchedules = await _teacherScheduleRepository.GetByClassroomIdAsync(
                    inputs.ClassroomId,
                    inputs.StartTime,
                    inputs.EndTime.AddHours(23).AddMinutes(59).AddSeconds(59)
                );

                // 检测teacherSchedules和_teacherSchedules的开始时间和结束时间是否有冲突
                foreach (var schedule in teacherSchedules)
                {
                    //找出有冲突的课表
                    var conflictSchedules = _teacherSchedules
                        .Where(ts =>
                            ts.TeacherScheduleDetails.Any(x =>
                                (
                                    (
                                        schedule.StartTime >= x.StartTime
                                        && schedule.StartTime <= x.EndTime
                                    )
                                    || (
                                        schedule.EndTime >= x.StartTime
                                        && schedule.EndTime <= x.EndTime
                                    )
                                    || (
                                        schedule.StartTime < x.StartTime
                                        && schedule.EndTime > x.EndTime
                                    )
                                )
                            )
                        )
                        .ToList();

                    //统计conflictSchedules的容量

                    var usedCapacity = conflictSchedules.Sum(x => x.Capacity);
                    var capacity = usedCapacity + schedule.Capacity;

                    if (capacity > classroom.Capacity)
                    {
                        businessExceptions.Add(
                            $"教室容量不足: {inputs.ClassroomId},容量:{classroom.Capacity},需求:{inputs.Capacity},已用容量:{usedCapacity}"
                        );
                    }
                }
            }
        }

        public async Task<TeacherScheduleDto> UpdateAsync(UpdateTeacherScheduleDto input)
        {
            var schedule = await _teacherScheduleRepository.GetByIdAsync(input.Id);
            if (schedule == null)
            {
                throw new ArgumentException($"课表不存在: {input.Id}");
            }

            // 验证教室是否存在
            if (input.ClassroomId.HasValue && input.ClassroomId != Guid.Empty)
            {
                var classroom = await _classroomRepository.GetByIdAsync(input.ClassroomId.Value);
                if (classroom == null)
                {
                    throw new ArgumentException($"教室不存在: {input.ClassroomId}");
                }
            }

            //// 如果更新了时间，验证时间是否合法且无冲突
            //if (input.StartTime.HasValue && input.EndTime.HasValue)
            //{
            //    if (input.StartTime >= input.EndTime)
            //    {
            //        throw new ArgumentException("上课时间必须早于下课时间");
            //    }

            //    var hasConflict = await _teacherScheduleRepository.HasTimeConflictAsync(
            //        schedule.TeacherId,
            //        input.StartTime.Value,
            //        input.EndTime.Value,
            //        schedule.Id
            //    );
            //    if (hasConflict)
            //    {
            //        throw new ArgumentException("该时间段已有其他课程安排");
            //    }

            //    schedule.StartTime = input.StartTime.Value;
            //    schedule.EndTime = input.EndTime.Value;
            //}
            /// <summary>
            /// 关联的教师
            /// </summary>


            schedule.Teacher = null;
            schedule.Course = null;
            schedule.Classroom = null;
            schedule.TeacherScheduleDetails = null;
            if (input.ClassroomId == Guid.Empty)
                schedule.ClassroomId = null;
            else
                schedule.ClassroomId = input.ClassroomId ?? schedule.ClassroomId;
            schedule.UnitPrice = input.UnitPrice ?? schedule.UnitPrice;
            schedule.Capacity = input.Capacity ?? schedule.Capacity;
            schedule.CourseId = input.CourseId.HasValue ? input.CourseId.Value : schedule.CourseId;
            schedule.TeacherId = input.TeacherId.HasValue
                ? input.TeacherId.Value
                : schedule.TeacherId;

            schedule.Status = input.Status ?? schedule.Status;
            schedule.Reason = input.Reason ?? schedule.Reason;
            schedule.Remarks = input.Remarks ?? schedule.Remarks;

            await _teacherScheduleRepository.UpdateAsync(schedule);
            return new TeacherScheduleDto() { Id = schedule.Id };
        }

        public async Task<TeacherScheduleDto> UpdateDetailsAsync(
            UpdateTeacherScheduleDetailsDto input
        )
        {
            var scheduleDetail = await _teacherScheduleDetailsRepository.GetByIdAsync(input.Id);
            if (scheduleDetail == null)
            {
                throw new ArgumentException($"课表详情不存在: {input.Id}");
            }
            scheduleDetail.Status = input.Status ?? scheduleDetail.Status;
            scheduleDetail.Reason = input.Reason ?? scheduleDetail.Reason;
            scheduleDetail.Remarks = input.Remarks ?? scheduleDetail.Remarks;
            scheduleDetail.CourseType = input.CourseType ?? scheduleDetail.CourseType;
            if (
                input.StartTime.HasValue
                && input.EndTime.HasValue
                && input.StartTime.Value < input.EndTime.Value
            )
            {
                scheduleDetail.StartTime = input.StartTime.Value;
                scheduleDetail.EndTime = input.EndTime.Value;
            }
            //scheduleDetail.TeacherSchedule = null;
            await _teacherScheduleDetailsRepository.UpdateAsync(scheduleDetail);

            return new TeacherScheduleDto()
            {
                Id = scheduleDetail.Id,
                Status = scheduleDetail.Status,
                Reason = scheduleDetail.Reason,
                Remarks = scheduleDetail.Remarks,
            };
        }

        public async Task DeleteAsync(Guid id)
        {
            var schedule = await _teacherScheduleRepository.GetByIdAsync(id);
            if (schedule == null)
            {
                throw new ArgumentException($"课表不存在: {id}");
            }

            var orderDetails = await _orderDetailService.GetByTeacherScheduleIdAsync(id);
            if (orderDetails != null && orderDetails.Count > 0)
            {
                // 获取学生姓名
                var studentNames = orderDetails.Select(x => x.Student.Name).ToList();
                throw new ArgumentException($"课表存在学生: {string.Join(",", studentNames)}");

                //throw new ArgumentException($"课表存在学生: {id}");
            }

            using (var transaction = await _context.Database.BeginTransactionAsync())
            {
                try
                {
                    //删除教师课表详情
                    var details =
                        await _teacherScheduleDetailsRepository.GetByTeacherScheduleIdAsync(id);
                    if (details != null)
                    {
                        await _teacherScheduleDetailsRepository.DeleteRangeAsync(details);
                    }
                    //删除教师课表
                    await _teacherScheduleRepository.DeleteAsync(id);

                    await transaction.CommitAsync();
                }
                catch (Exception ex)
                {
                    await transaction.RollbackAsync();
                    throw new Exception("删除教师课表失败", ex);
                }
            }
        }

        public async Task DeleteDetailsAsync(List<Guid> ids)
        {
            var scheduleDetails = await _teacherScheduleDetailsRepository.GetByIdsAsync(ids);
            if (scheduleDetails == null || !scheduleDetails.Any())
            {
                throw new ArgumentException($"课表详情不存在: {string.Join(",", ids)}");
            }

            //使用事务
            using (var transaction = await _context.Database.BeginTransactionAsync())
            {
                try
                {
                    // 清空当前上下文跟踪的所有实体
                    _context.ChangeTracker.Clear();

                    foreach (var detail in scheduleDetails)
                    {
                        // 获取相关联的学生课表详情
                        var studentScheduleDetails =
                            await _studentScheduleDetailsRepository.GetByTeacherScheduleDetailsIdAsync(
                                detail.Id
                            );

                        if (studentScheduleDetails != null && studentScheduleDetails.Count > 0)
                        {
                            // 使用SQL直接删除学生课表详情，避免实体跟踪问题，使用逻辑删除
                            await _context.Database.ExecuteSqlRawAsync(
                                "UPDATE student_schedules_details SET IsDeleted = 1,UpdatedAt = NOW(),UpdatedBy = {0} WHERE TeacherScheduleDetailsId IN ({1})",
                                _currentUserService.UserId ?? Guid.Empty,
                                string.Join(",", scheduleDetails.Select(x => x.Id).ToList())
                            );
                        }
                    }

                    // 使用SQL直接删除教师课表详情，使用逻辑删除
                    await _context.Database.ExecuteSqlRawAsync(
                        "UPDATE teacher_schedules_details SET IsDeleted = 1,UpdatedAt = NOW(),UpdatedBy = {0} WHERE Id IN ({1})",
                        _currentUserService.UserId ?? Guid.Empty,
                        string.Join(",", scheduleDetails.Select(x => x.Id).ToList())
                    );

                    await transaction.CommitAsync();
                }
                catch (Exception ex)
                {
                    await transaction.RollbackAsync();
                    throw new Exception("删除教师课表详情失败", ex);
                }
            }
        }

        public async Task<List<TeacherScheduleDto>> GetByTeacherIdAsync(Guid teacherId)
        {
            var schedules = await _teacherScheduleRepository.GetByTeacherIdAsync(teacherId);
            return _mapper.Map<List<TeacherScheduleDto>>(schedules);
        }

        public async Task<List<TeacherScheduleDto>> GetByCourseIdAsync(Guid courseId)
        {
            var schedules = await _teacherScheduleRepository.GetByCourseIdAsync(courseId);
            return _mapper.Map<List<TeacherScheduleDto>>(schedules);
        }

        public async Task<PagedResult<TeacherScheduleDto>> GetStatisticsPagedListAsync(
            TeacherScheduleStatisticsPageRequest pageRequest
        )
        {
            return await GetStatisticsPagedList2Async(pageRequest);
            //var schedules = await _teacherScheduleRepository.GetStatisticsPagedListAsync(
            //    pageRequest
            //);

            //// 获取所有组ID
            //var teacherScheduleIds = schedules.Items.Select(ts => ts.Id).ToList();

            //// 获取每个组已报名人数
            //var enrolledCounts =
            //    await _studentScheduleRepository.GetEnrolledCountByTeacherScheduleIdsAsync(
            //        teacherScheduleIds
            //    );

            ////var teacherSchedules = await _teacherScheduleRepository.GetByGroupIdsAsync(schedules.Items.Select(ts => ts.GroupId).ToList());

            //// 映射并设置报名人数
            //var dtos = _mapper.Map<List<TeacherScheduleDto>>(schedules.Items);
            //foreach (var dto in dtos)
            //{
            //    var enrolledCount = enrolledCounts.FirstOrDefault(x =>
            //        x.TeacherScheduleId == dto.Id
            //    );
            //    dto.EnrolledCount = enrolledCount.EnrolledCount;
            //    dto.GroupId = dto.Id;
            //    var courseCount = schedules
            //        .Items.FirstOrDefault(x => x.Id == dto.Id)
            //        .TeacherScheduleDetails.Where(ts => ts.Status == ScheduleStatus.Normal)
            //        .ToList()
            //        .Count;
            //    dto.CourseCount = courseCount;
            //}

            //return new PagedResult<TeacherScheduleDto> { Total = schedules.Total, Items = dtos };
        }

        public async Task<PagedResult<TeacherScheduleDto>> GetStatisticsPagedList2Async(
            TeacherScheduleStatisticsPageRequest pageRequest
        )
        {
            //TODO: 如果学生不存在，则不包含
            var orderDetails = _context
                .OrderDetails.AsNoTracking()
                .Include(o => o.Student)
                .Where(o => !o.Student.IsDeleted)
                .GroupBy(o => o.TeacherScheduleId)
                .Select(g => new
                {
                    TeacherScheduleId = g.Key,
                    EnrolledCount = g.Count(),
                    Students = g.Select(x => x.Student).ToList(),
                });

            //根据pageRequest的条件过滤
            var query = _context.TeacherSchedules.AsQueryable();

            //添加过滤条件
            if (pageRequest.GroupId.HasValue)
            {
                query = query.Where(ts => ts.Id == pageRequest.GroupId);
            }
            if (pageRequest.TeacherId.HasValue)
            {
                query = query.Where(ts => ts.TeacherId == pageRequest.TeacherId);
            }
            if (pageRequest.CourseId.HasValue)
            {
                query = query.Where(ts => ts.CourseId == pageRequest.CourseId);
            }
            if (pageRequest.StartDate.HasValue && pageRequest.EndDate.HasValue)
            {
                query = query.Where(ts =>
                    // ts.StartTime >= pageRequest.StartDate && ts.EndTime <= pageRequest.EndDate
                    ts.TeacherScheduleDetails.Any(x =>
                        x.StartTime >= pageRequest.StartDate && x.EndTime <= pageRequest.EndDate
                    )
                );
            }

            // 先计算总记录数
            var totalCount = await query.CountAsync();

            //应用Include和分页
            var teacherSchedules = await query
                .Include(ts => ts.Teacher)
                .Include(ts => ts.Course)
                .Include(ts => ts.Classroom)
                .Include(ts => ts.TeacherScheduleDetails)
                .Skip((pageRequest.PageIndex - 1) * pageRequest.PageSize)
                .Take(pageRequest.PageSize)
                .ToListAsync();

            //query和TeacherScheduleDetails进行关联查询统计，使用左外连接
            var result = teacherSchedules
                .GroupJoin(
                    orderDetails,
                    ts => ts.Id,
                    tsd => tsd.TeacherScheduleId,
                    (ts, tsd) => new { ts, tsd }
                )
                .SelectMany(x => x.tsd.DefaultIfEmpty(), (ts, tsd) => new { ts = ts.ts, tsd });
            ;

            //var result = teacherSchedules.GroupJoin(orderDetails, ts => ts.Id, tsd => tsd.TeacherScheduleId, (ts, tsd) => new { ts, tsd });

            var dtos = result
                .Select(x => new TeacherScheduleDto()
                {
                    EnrolledCount = x.tsd?.EnrolledCount ?? 0,
                    CourseCount = x.ts.TeacherScheduleDetails.Count,
                    GroupId = x.ts.Id,
                    Id = x.ts.Id,
                    TeacherId = x.ts.TeacherId,
                    CourseId = x.ts.CourseId,
                    ClassroomId = x.ts.ClassroomId,
                    UnitPrice = x.ts.UnitPrice,
                    Capacity = x.ts.Capacity,
                    StartTime = x.ts.StartTime,
                    EndTime = x.ts.EndTime,
                    Status = x.ts.Status,
                    Reason = x.ts.Reason,
                    Remarks = x.ts.Remarks,
                    CalenderColor = x.ts.Course?.CalendarColor ?? string.Empty,
                    ClassroomName = x.ts.Classroom?.Name ?? string.Empty,
                    CourseName = x.ts.Course?.Name ?? string.Empty,
                    TeacherName = x.ts.Teacher?.Name ?? string.Empty,
                    Students =
                        x.tsd?.Students.Select(x => new StudentDto()
                            {
                                Id = x.Id,
                                Name = x.Name,
                                StudentNo = x.StudentNo,
                                Phone = x.Phone,
                                Email = x.Email,
                            })
                            .ToList() ?? new List<StudentDto>(),
                    TeacherScheduleDetails = x
                        .ts.TeacherScheduleDetails.Select(x => new TeacherScheduleDetailsDto()
                        {
                            Id = x.Id,
                            StartTime = x.StartTime,
                            EndTime = x.EndTime,
                            CourseType = x.CourseType,
                            Status = x.Status,
                            Reason = x.Reason,
                        })
                        .ToList(),
                })
                .ToList();

            var pagedResult = new PagedResult<TeacherScheduleDto>()
            {
                Total = totalCount,
                Items = dtos,
            };
            return pagedResult;

            // var schedules = await _teacherScheduleRepository.GetStatisticsPagedListAsync(
            //     pageRequest
            // );

            // // 获取所有组ID
            // var teacherScheduleIds = schedules.Items.Select(ts => ts.Id).ToList();

            // // 获取每个组已报名人数
            // var enrolledCounts =
            //     await _studentScheduleRepository.GetEnrolledCountByTeacherScheduleIdsAsync(
            //         teacherScheduleIds
            //     );

            // //var teacherSchedules = await _teacherScheduleRepository.GetByGroupIdsAsync(schedules.Items.Select(ts => ts.GroupId).ToList());

            // // 映射并设置报名人数
            // var dtos = _mapper.Map<List<TeacherScheduleDto>>(schedules.Items);
            // foreach (var dto in dtos)
            // {
            //     var enrolledCount = enrolledCounts.FirstOrDefault(x =>
            //         x.TeacherScheduleId == dto.Id
            //     );
            //     dto.EnrolledCount = enrolledCount.EnrolledCount;
            //     dto.GroupId = dto.Id;
            //     var courseCount = schedules
            //         .Items.FirstOrDefault(x => x.Id == dto.Id)
            //         .TeacherScheduleDetails.Where(ts => ts.Status == ScheduleStatus.Normal)
            //         .ToList()
            //         .Count;
            //     dto.CourseCount = courseCount;
            // }

            // return new PagedResult<TeacherScheduleDto> { Total = schedules.Total, Items = dtos };
        }

        public async Task<TeacherScheduleDto> CreateDetailsAsync(
            CreateTeacherScheduleDetailsDto input
        )
        {
            //验证是否在课程时间范围内和课表详情时间是否有冲突，根据TeacherScheduleId
            var teacherSchedule = await _teacherScheduleRepository.GetByIdAsync(
                input.TeacherScheduleId
            );
            if (teacherSchedule == null)
            {
                throw new ArgumentException($"教师课表不存在: {input.TeacherScheduleId}");
            }
            //if (
            //    input.StartTime < teacherSchedule.StartTime
            //    || input.EndTime > teacherSchedule.EndTime
            //)
            //{
            //    // throw new ArgumentException(
            //    //     $"课表详情时间不在教师课表时间范围内: {input.StartTime} - {input.EndTime}"
            //    // );
            //    //主表修改时间
            //    teacherSchedule.StartTime = input.StartTime;
            //    teacherSchedule.EndTime = input.EndTime;
            //    await _teacherScheduleRepository.UpdateAsync(teacherSchedule);
            //}
            if (
                teacherSchedule.TeacherScheduleDetails != null
                && teacherSchedule.TeacherScheduleDetails.Count > 0
            )
            {
                var hasConflict = teacherSchedule
                    .TeacherScheduleDetails.Where(x => x.Status == ScheduleStatus.Normal)
                    .Any(x =>
                        (input.StartTime >= x.StartTime && input.StartTime <= x.EndTime)
                        || (input.EndTime >= x.StartTime && input.EndTime <= x.EndTime)
                        || (input.StartTime < x.StartTime && input.EndTime > x.EndTime)
                    );
                if (hasConflict)
                {
                    throw new ArgumentException(
                        $"课表详情时间与已有课表详情时间冲突: {input.StartTime} - {input.EndTime}"
                    );
                }
            }

            var scheduleDetail = await _teacherScheduleDetailsRepository.AddAsync(
                new TeacherScheduleDetails()
                {
                    Id = Guid.NewGuid(),
                    TeacherScheduleId = input.TeacherScheduleId,
                    StartTime = input.StartTime,
                    EndTime = input.EndTime,
                    Remarks = input.Remarks ?? string.Empty,
                    Status = ScheduleStatus.Normal,
                    IsForceCheck = true,
                }
            );

            var dto = new TeacherScheduleDto() { Id = scheduleDetail.Id };

            return dto;
        }

        //教师课表详情分页查询
        public async Task<PagedResult<TeacherScheduleDetailsDto>> GetPagedDetailsListAsync(
            TeacherSchedulePageRequest pageRequest
        )
        {
            var baseQuery = _context
                .TeacherScheduleDetails.Where(ts => ts.TeacherSchedule != null)
                .Include(ts => ts.TeacherSchedule.Teacher)
                .Include(ts => ts.TeacherSchedule.Course)
                .Include(ts => ts.TeacherSchedule.Classroom)
                .AsQueryable();

            // 应用所有过滤条件
            if (pageRequest.TeacherId.HasValue)
            {
                baseQuery = baseQuery.Where(ts =>
                    ts.TeacherSchedule.TeacherId == pageRequest.TeacherId
                );
            }
            if (pageRequest.ClassroomId.HasValue)
            {
                baseQuery = baseQuery.Where(ts =>
                    ts.TeacherSchedule.ClassroomId == pageRequest.ClassroomId
                );
            }
            if (pageRequest.CourseType.HasValue)
            {
                baseQuery = baseQuery.Where(ts => ts.CourseType == pageRequest.CourseType);
            }
            if (pageRequest.GroupId.HasValue)
            {
                baseQuery = baseQuery.Where(ts => ts.TeacherScheduleId == pageRequest.GroupId);
            }
            if (pageRequest.CourseId.HasValue)
            {
                baseQuery = baseQuery.Where(ts =>
                    ts.TeacherSchedule.CourseId == pageRequest.CourseId
                );
            }
            if (pageRequest.StartDate.HasValue && pageRequest.EndDate.HasValue)
            {
                baseQuery = baseQuery.Where(ts =>
                    ts.StartTime >= pageRequest.StartDate && ts.EndTime <= pageRequest.EndDate
                );
            }

            if (!string.IsNullOrEmpty(pageRequest.Remarks))
            {
                baseQuery = baseQuery.Where(ts => ts.Remarks.Contains(pageRequest.Remarks));
            }
            // var details = await _teacherScheduleDetailsRepository.GetPagedDetailsListAsync(
            //     pageRequest
            // );
            var details = await baseQuery.ToListAsync();
            //根据details.items.id 关联查询StudentScheduleDetails.teacherScheduleDetailsId 查询StudentScheduleDetails.OrderDetail.Student的列表

            var studentScheduleDetails =
                await _studentScheduleDetailsRepository.GetByTeacherScheduleDetailsIdAsync(
                    details.Select(x => x.Id).ToList(),
                    pageRequest.StudentId
                );

            var studentScheduleDetailsList = studentScheduleDetails
                .GroupBy(x => x.TeacherScheduleDetailsId)
                .Select(x => new
                {
                    TeacherScheduleDetailsId = x.Key,
                    Students = x.Where(y => y.OrderDetail != null)
                        .Select(y => y.OrderDetail.Student)
                        .ToList(), //导致了空异常，因为OrderDetail.Student为null
                    // OrderDetailId = x.FirstOrDefault()?.OrderDetailId ?? Guid.Empty,
                })
                .ToList();

            //手动映射
            if (pageRequest.StudentId.HasValue)
            {
                details = details
                    .Where(x =>
                        studentScheduleDetailsList.Any(y =>
                            y.TeacherScheduleDetailsId == x.Id
                            && y.Students.Any(z => z.Id == pageRequest.StudentId)
                        )
                    )
                    .ToList();
            }

            //将details进行分页
            var pagedDetails = details
                .OrderBy(ts => ts.TeacherSchedule.TeacherId)
                .ThenBy(ts => ts.StartTime)
                .Skip((pageRequest.PageIndex - 1) * pageRequest.PageSize)
                .Take(pageRequest.PageSize)
                .ToList();

            var dtos = pagedDetails
                .Select(x => new TeacherScheduleDetailsDto()
                {
                    Id = x.Id,
                    StartTime = x.StartTime,
                    EndTime = x.EndTime,
                    Status = x.Status,
                    CourseType = x.CourseType,
                    Reason = x.Reason ?? string.Empty,
                    Remarks = x.Remarks ?? string.Empty,
                    // OrderDetailId = studentScheduleDetailsList
                    //     .FirstOrDefault(s => s.TeacherScheduleDetailsId == x.Id)
                    //     ?.OrderDetailId ?? Guid.Empty,
                    TeacherSchedule = new TeacherScheduleDto()
                    {
                        Id = x.TeacherSchedule.Id,
                        TeacherId = x.TeacherSchedule.TeacherId,
                        TeacherName = x.TeacherSchedule.Teacher?.Name ?? string.Empty,
                        CourseId = x.TeacherSchedule.CourseId,
                        CourseName = x.TeacherSchedule.Course?.Name ?? string.Empty,
                        ClassroomId = x.TeacherSchedule.ClassroomId,
                        ClassroomName = x.TeacherSchedule.Classroom?.Name ?? string.Empty,
                        UnitPrice = x.TeacherSchedule.UnitPrice,
                        Capacity = x.TeacherSchedule.Capacity,
                        StartTime = x.TeacherSchedule.StartTime,
                        EndTime = x.TeacherSchedule.EndTime,
                        Status = x.TeacherSchedule.Status,
                        Reason = x.TeacherSchedule.Reason,
                        Remarks = x.TeacherSchedule.Remarks,
                        CalenderColor = x.TeacherSchedule.Course?.CalendarColor ?? string.Empty,
                    },
                    Students =
                        studentScheduleDetailsList
                            .FirstOrDefault(s => s.TeacherScheduleDetailsId == x.Id)
                            ?.Students.Select(y => _mapper.Map<StudentDto>(y))
                            .ToList() ?? new List<StudentDto>(),
                })
                .ToList();
            return new PagedResult<TeacherScheduleDetailsDto>
            {
                Total = details.Count,
                Items = dtos,
            };
        }
    }
}
